package cn.wikiflyer.beikang.paywx;

import java.io.StringReader;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Random;

import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import org.xmlpull.v1.XmlPullParser;

import cn.wikiflyer.beikang.R;

import com.tencent.mm.sdk.modelpay.PayReq;
import com.tencent.mm.sdk.openapi.IWXAPI;
import com.tencent.mm.sdk.openapi.WXAPIFactory;

import android.app.ProgressDialog;
import android.content.Context;
import android.os.AsyncTask;
import android.util.Log;
import android.util.Xml;
import android.widget.Toast;

/**
 * @author maizi PayWxObject.java 2015年6月2日 微信支付
 */
public class PayWxObject {
	private static final String TAG = "PayWxObject";

	private StringBuffer sb;
	private PayReq req;
	private final IWXAPI msgApi;
	private Context context;
	private String productXmlInfo;

	public PayWxObject(Context context) {
		this.context = context;
		sb = new StringBuffer();
		req = new PayReq();
		msgApi = WXAPIFactory.createWXAPI(context, null);
		msgApi.registerApp(Constants.APP_ID);
	}
	/** 支付
	 */
	public void startPay(){
		if (!msgApi.isWXAppInstalled()) {
			Toast.makeText(context, "微信未安装", Toast.LENGTH_SHORT).show();
			return ;
		}
		GetPrepayIdTask getPrepayIdTask = new GetPrepayIdTask();
		getPrepayIdTask.execute();
	}
	/** @return 生成随机字符串
	 */
	private String genNonceStr() {
		Random random = new Random();
		return MD5.getMessageDigest(String.valueOf(random.nextInt(10000))
				.getBytes());
	}
	
	/**构建产品订单信息
	 */
	public void buildProductArgs(UnifiedOrderBean bean) {
		StringBuffer xml = new StringBuffer();
		try {
			String nonceStr = genNonceStr();
			xml.append("</xml>");
			List<NameValuePair> packageParams = new LinkedList<NameValuePair>();
			packageParams
					.add(new BasicNameValuePair("appid", Constants.APP_ID));
			packageParams.add(new BasicNameValuePair("body", bean.body));
			packageParams.add(new BasicNameValuePair("detail", bean.detail));
			packageParams.add(new BasicNameValuePair("mch_id", Constants.MCH_ID));
			packageParams.add(new BasicNameValuePair("nonce_str", nonceStr));
			packageParams.add(new BasicNameValuePair("notify_url",bean.notify_url));
			packageParams.add(new BasicNameValuePair("out_trade_no",bean.out_trade_no));
			packageParams.add(new BasicNameValuePair("spbill_create_ip",bean.spbill_create_ip));
			packageParams.add(new BasicNameValuePair("total_fee", ""+bean.total_fee));
			packageParams.add(new BasicNameValuePair("trade_type", "APP"));
			String sign = genPackageSign(packageParams);
			packageParams.add(new BasicNameValuePair("sign", sign));
			productXmlInfo = toXml(packageParams);
		} catch (Exception e) {
			Log.e(TAG, "genProductArgs fail, ex = " + e.getMessage());
			productXmlInfo = "";
		}
	}
	/** @param params  ListParams转化xml
	 */
	private String toXml(List<NameValuePair> params) {
		StringBuilder sb = new StringBuilder();
		sb.append("<xml>");
		for (int i = 0; i < params.size(); i++) {
			sb.append("<" + params.get(i).getName() + ">");

			sb.append(params.get(i).getValue());
			sb.append("</" + params.get(i).getName() + ">");
		}
		sb.append("</xml>");

		Log.e("orion", sb.toString());
		return sb.toString();
	}
	/**生成签名
	 */
	private String genPackageSign(List<NameValuePair> params) {
		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < params.size(); i++) {
			sb.append(params.get(i).getName());
			sb.append('=');
			sb.append(params.get(i).getValue());
			sb.append('&');
		}
		sb.append("key=");
		sb.append(Constants.API_KEY);
		String packageSign = MD5.getMessageDigest(sb.toString().getBytes())
				.toUpperCase();
		Log.e("orion", "packageSign :" + packageSign);
		return packageSign;
	}
	private long genTimeStamp() {
		return System.currentTimeMillis() / 1000;
	}
	private String genAppSign(List<NameValuePair> params) {
		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < params.size(); i++) {
			sb.append(params.get(i).getName());
			sb.append('=');
			sb.append(params.get(i).getValue());
			sb.append('&');
		}
		sb.append("key=");
		sb.append(Constants.API_KEY);
		this.sb.append("sign str\n" + sb.toString() + "\n\n");
		String appSign = MD5.getMessageDigest(sb.toString().getBytes())
				.toUpperCase();
		Log.e("orion", "appSign :" + appSign);
		return appSign;
	}
	/**获取支付请求（请求支付   ）
	 */
	public void genPayReq(Map<String, String> resultunifiedorder) {
		req.appId = Constants.APP_ID;
		req.partnerId = Constants.MCH_ID;
		req.prepayId = resultunifiedorder.get("prepay_id");
		req.packageValue = "Sign=WXPay";
		req.nonceStr = genNonceStr();
		req.timeStamp = String.valueOf(genTimeStamp());
		List<NameValuePair> signParams = new LinkedList<NameValuePair>();
		signParams.add(new BasicNameValuePair("appid", req.appId));
		signParams.add(new BasicNameValuePair("noncestr", req.nonceStr));
		signParams.add(new BasicNameValuePair("package", req.packageValue));
		signParams.add(new BasicNameValuePair("partnerid", req.partnerId));
		signParams.add(new BasicNameValuePair("prepayid", req.prepayId));
		signParams.add(new BasicNameValuePair("timestamp", req.timeStamp));
		req.sign = genAppSign(signParams);
		sb.append("sign\n" + req.sign + "\n\n");
		Log.e("orion", "signParams :" + signParams.toString());
		//发送支付请求
		msgApi.registerApp(Constants.APP_ID);
		msgApi.sendReq(req);
	}
	/**获取支付请求（请求支付   ）
	 */
	public void genPayReq(String prepayId) {
		req.appId = Constants.APP_ID;
		req.partnerId = Constants.MCH_ID;
		req.prepayId = prepayId;
		req.packageValue = "Sign=WXPay";
		req.nonceStr = genNonceStr();
		req.timeStamp = String.valueOf(genTimeStamp());
		List<NameValuePair> signParams = new LinkedList<NameValuePair>();
		signParams.add(new BasicNameValuePair("appid", req.appId));
		signParams.add(new BasicNameValuePair("noncestr", req.nonceStr));
		signParams.add(new BasicNameValuePair("package", req.packageValue));
		signParams.add(new BasicNameValuePair("partnerid", req.partnerId));
		signParams.add(new BasicNameValuePair("prepayid", req.prepayId));
		signParams.add(new BasicNameValuePair("timestamp", req.timeStamp));
		req.sign = genAppSign(signParams);
		sb.append("sign\n" + req.sign + "\n\n");
		Log.e("orion", "signParams :" + signParams.toString());
		//发送支付请求
		msgApi.registerApp(Constants.APP_ID);
		msgApi.sendReq(req);
	}

	/** @author maizi
	 * PayWxObject.java
	 * 2015年6月2日
	 * 获取PropayId的线程
	 */
	private class GetPrepayIdTask extends
			AsyncTask<Void, Void, Map<String, String>> {
		private ProgressDialog dialog;
		@Override
		protected void onPostExecute(Map<String, String> result) {
			if (dialog != null) {
				dialog.dismiss();
			}
			sb.append("prepay_id\n" + result.get("prepay_id") + "\n\n");
			genPayReq(result);
		}
		@Override
		protected void onPreExecute() {
			super.onPreExecute();
			dialog = ProgressDialog.show(context, "提示", "正在获取预支付订单...");
			dialog.setCanceledOnTouchOutside(false);
		}
		@Override
		protected void onCancelled() {
			super.onCancelled();
		}
		@Override
		protected Map<String, String> doInBackground(Void... params) {
			String url = String.format(Constants.PrepayUrl);
			String entity = productXmlInfo;
			Log.e("orion", entity);
			byte[] buf = Util.httpPost(url, entity);
			String content = new String(buf);
			Log.e("orion", "content :" + content);
			Map<String, String> xml = decodeXml(content);
			return xml;
		}
	}
	/** @param content  将String转化为xml
	 */
	public Map<String, String> decodeXml(String content) {
		try {
			Map<String, String> xml = new HashMap<String, String>();
			XmlPullParser parser = Xml.newPullParser();
			parser.setInput(new StringReader(content));
			int event = parser.getEventType();
			while (event != XmlPullParser.END_DOCUMENT) {
				String nodeName = parser.getName();
				switch (event) {
				case XmlPullParser.START_DOCUMENT:
					break;
				case XmlPullParser.START_TAG:
					if ("xml".equals(nodeName) == false) {
						// 实例化student对象
						xml.put(nodeName, parser.nextText());
					}
					break;
				case XmlPullParser.END_TAG:
					break;
				}
				event = parser.next();
			}
			return xml;
		} catch (Exception e) {
			Log.e("orion", e.toString());
		}
		return null;
	}

}
